package com.demo.util;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUniqueStringGenerator {

    private final RedisTemplate<String, String> redisTemplate;
    private final DefaultRedisScript<String> script;

    private static final String LUA_SCRIPT =
            "local charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' \n" +
            "local result = 'M' \n" +
            "math.randomseed(tonumber(redis.call('TIME')[1])) \n" +
            "for i = 1, 5 do \n" +
            "    local index = math.random(1, #charset) \n" +
            "    result = result .. string.sub(charset, index, index) \n" +
            "end \n" +
            "local key = KEYS[1] .. result \n" +
            "if redis.call('setnx', key, result) == 1 then\n" +
            "    return result \n" +
            "else \n" +
            "    return ''\n" +
            "end";

    public RedisUniqueStringGenerator(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.script = new DefaultRedisScript<>();
        this.script.setScriptText(LUA_SCRIPT);
        this.script.setResultType(String.class);
    }

    /**
     * 生成唯一字符串，带重试机制
     */
    public String generateWithRetry(String keyPrefix, int maxRetries) {
        for (int i = 0; i < maxRetries; i++) {
            try {
                String result = redisTemplate.execute(
                        script,
                        Collections.singletonList(keyPrefix)
                );
                if (!result.isEmpty()) {
                    return result;
                }
                // 短暂休眠后重试
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("生成过程被中断", e);
            }
        }
        throw new RuntimeException("在 " + maxRetries + " 次尝试后仍无法生成唯一字符串");
    }


}